#!/usr/bin/env python

# Background Library: run stuff in the backround
#
## Basic Usage
#
# import time
# import background
# @background.task
# def work():
#     # Do something expensive here.
#     time.sleep(10)
# for _ in range(100):
#     work()
#
## Advanced Usage
#
# import time
# import background
# # Use 40 background threads.
# background.n = 40
# @background.task
# def work():
#     time.sleep(10)
# @background.callback
# def work_callback(future):
#     print(future)
# for _ in range(100):
#     work()

import multiprocessing
import concurrent.futures

def default_n():
    return multiprocessing.cpu_count()

n = default_n()
pool = concurrent.futures.ThreadPoolExecutor(max_workers=n)
callbacks = []
results = []

def run(f, *args, **kwargs):

    pool._max_workers = n
    pool._adjust_thread_count()

    f = pool.submit(f, *args, **kwargs)
    results.append(f)

    return f

def task(f):
    def do_task(*args, **kwargs):
        result = run(f, *args, **kwargs)

        for cb in callbacks:
            result.add_done_callback(cb)

        return result
    return do_task


def callback(f):
    callbacks.append(f)

    def register_callback():
        f()

    return register_callback